package service

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/pkg/errors"
	"gorm.io/gorm"
	"mall/api/bilinadmin"
	"mall/api/mall"
	"mall/api/pay"
	"mall/api/prod"
	"mall/internal/constant"
	"mall/internal/model"
	"mall/pkg/ecode"
	"mall/pkg/log"
	"mall/pkg/util"
	"strings"
)

// 查看商城首页
func (s *Service) GetMallMainPage(ctx context.Context, req *mall.GetMallMainPageRequest) (
	resp *mall.GetMallMainPageResp, err error) {
	var config *model.Config
	if config, err = s.dao.GetConfig(ctx, req.Token.SgId); err != nil {
		if errors.Cause(err) == gorm.ErrRecordNotFound {
			err = constant.ErrMallNotOpen
			return
		}
		return
	}
	bizType := bilinadmin.BizTypeEnum(config.OperationMode)
	resp = &mall.GetMallMainPageResp{
		OperationMode: bizType,
		AllowBooking:  config.AllowBooking,
		BookingDays:   config.BookingDays,
	}
	if bizType == bilinadmin.BizTypeEnum_platform {
		// 平台模式需要获取门店列表
		if resp.Pages, err = s.downstream.GetStoreListByLocation(
			ctx, req.Token.SgId, req.Latitude, req.Longitude, bizType); err != nil {
			return
		}
	} else {
		resp.Pages = make([]*mall.StoreSimpleView, 0)
	}
	return
}

func (s *Service) loadProdsByIds(ctx context.Context, sgId, pStoreId uint32, prodIds []uint64) (
	prods []*mall.CustomerProd, err error) {
	// 获取货架商品
	var (
		shelfProds []*model.ShelfProd
		shelfSkus  []*model.ShelfSku
	)
	if shelfProds, err = s.dao.FindOnShelfProdsByProdIds(ctx, sgId, pStoreId, prodIds); err != nil {
		return
	}
	if shelfSkus, err = s.dao.FindShelfSkusByProdIds(ctx, sgId, pStoreId, prodIds); err != nil {
		return
	}
	skuMap := make(map[uint64][]*model.ShelfSku)
	priceRangeDict := getPriceRangeDict(shelfSkus)
	for _, sku := range shelfSkus {
		if _, ok := skuMap[sku.ProdId]; !ok {
			skuMap[sku.ProdId] = make([]*model.ShelfSku, 0)
		}
		skuMap[sku.ProdId] = append(skuMap[sku.ProdId], sku)
	}
	prods = make([]*mall.CustomerProd, len(shelfProds))
	for i, shelfProd := range shelfProds {
		skus, ok := skuMap[shelfProd.ProdId]
		if !ok {
			log.FromContext(ctx).Info(fmt.Sprintf("货架商品%d无法加载规格", shelfProd.ProdId))
			continue
		}
		groups := make([]*prod.ProdPropertyGroupView, len(shelfProd.SyncGroups))
		groupDetailMap := make(map[string][]string)
		if err = json.Unmarshal(shelfProd.SyncGroupDetails, &groupDetailMap); err != nil {
			err = ecode.WithStack(err)
			return
		}
		for j, groupName := range shelfProd.SyncGroups {
			groups[j] = &prod.ProdPropertyGroupView{
				Name:  groupName,
				Items: groupDetailMap[groupName],
			}
		}
		prods[i] = &mall.CustomerProd{
			Id:            shelfProd.ProdId,
			Name:          getCustomName(shelfProd),
			PriceRange:    priceRangeDict[shelfProd.ProdId],
			TitlePic:      shelfProd.SyncPic,
			Sales:         0,
			HasProperties: len(skus) > 1,
			Groups:        groups,
			Skus:          make([]*prod.SkuView, len(skus)),
		}
		for j, sku := range skus {
			prods[i].Skus[j] = &prod.SkuView{
				Id:     sku.SkuId,
				Name:   strings.Join(sku.SyncItems, "/"),
				Price:  uint32(getCustomPrice(sku)),
				Weight: sku.SyncWeight,
				Items:  sku.SyncItems,
			}
		}
	}
	return
}

// 查看商城装修
func (s *Service) GetMallPage(ctx context.Context, req *mall.CustomerStoreRequest) (
	resp *mall.GetMallPageResp, err error) {
	var (
		decoration *model.Decoration
		sourceType pay.SourceType
	)
	if sourceType, err = getSourceType(req.Token); err != nil {
		return
	}
	if decoration, err = s.dao.GetDecoration(ctx, req.Token.SgId, req.Id, uint8(sourceType)); err != nil {
		if errors.Cause(err) == gorm.ErrRecordNotFound {
			err = nil
			var config *model.Config
			if config, err = s.dao.GetConfig(ctx, req.Token.SgId); err != nil {
				if errors.Cause(err) == gorm.ErrRecordNotFound {
					err = ecode.AppendMessage(constant.ErrNeedRefresh, "商城尚未开通，无法编辑配置")
					return
				}
				return
			}
			resp = &mall.GetMallPageResp{}
			if resp.DecorationInfo, err = s.dao.GetDecorationTemplate(
				ctx, config.OperationMode, req.Id == 0); err != nil {
				return
			}

		} else {
			return
		}
	} else {
		resp = &mall.GetMallPageResp{
			DecorationInfo: decoration.Decoration,
		}
		if len(decoration.ProdIds) != 0 {
			if resp.Prods, err = s.loadProdsByIds(
				ctx, req.Token.SgId, req.Id, util.FormatIntArrayToInt64Array(decoration.ProdIds)); err != nil {
				return
			}
		}
	}

	if req.Id != 0 {
		var stores []*mall.StoreSimpleView
		if stores, err = s.downstream.GetStoreListByStoreIds(ctx, []int{int(req.Id)}); err != nil {
			return
		}
		if len(stores) == 1 {
			resp.PageName = stores[0].Name
		}
	} else {
		if resp.PageName, err = s.downstream.GetBrandName(ctx, req.Token.SgId); err != nil {
			return
		}
	}
	return
}

func (s *Service) GetMallProds(ctx context.Context, req *mall.CustomerProdsRequest) (
	resp *mall.GetMallProdsResp, err error) {
	resp = &mall.GetMallProdsResp{}
	if resp.Prods, err = s.loadProdsByIds(
		ctx, req.Token.SgId, req.Id, req.ProdIds); err != nil {
		return
	}
	return
}

// 查看商城货架
func (s *Service) GetCustomerShelf(ctx context.Context, req *mall.GetCustomerShelfRequest) (
	resp *mall.GetCustomerShelfResp, err error) {
	var prodIds []uint64
	resp = &mall.GetCustomerShelfResp{}
	if prodIds, resp.Total, err = s.dao.FindShelfProdIdsByPage(
		ctx, req.Token.SgId, req.Id, req.PageNo, req.PageSize, req.GroupId, req.Query); err != nil {
		return
	}
	if resp.Prods, err = s.loadProdsByIds(ctx, req.Token.SgId, req.Id, prodIds); err != nil {
		return
	}
	return
}

// 查看商品详情
func (s *Service) GetCustomerProd(ctx context.Context, req *mall.GetCustomerProdRequest) (
	resp *mall.GetCustomerProdResp, err error) {

	var (
		shelfProd *model.ShelfProd
		skus      []*model.ShelfSku
		prodView  *prod.ProdView
	)
	if prodView, err = s.downstream.GetProdInfo(
		ctx, req.Token.SgId, 0, req.ProdId, true); err != nil {
		return
	}
	if shelfProd, err = s.dao.GetShelfProd(ctx, req.ProdId, req.Token.SgId, req.Id); err != nil {
		if errors.Cause(err) != gorm.ErrRecordNotFound {
			return
		}
		// 允许搜索货架上没有的商品
		err = nil
		priceRange := []uint64{uint64(prodView.Skus[0].Price), uint64(prodView.Skus[0].Price)}
		for _, sku := range prodView.Skus[1:] {
			price := uint64(sku.Price)
			if priceRange[0] > price {
				priceRange[0] = price
			} else if priceRange[1] < price {
				priceRange[1] = price
			}
		}
		resp = &mall.GetCustomerProdResp{
			Id:                req.ProdId,
			Name:              prodView.Name,
			PriceRange:        priceRange,
			Sales:             0,
			HasProperties:     len(prodView.Skus) > 1,
			Unit:              prodView.Unit,
			TitlePics:         prodView.TitlePics,
			DetailPics:        prodView.DetailPics,
			DetailDescription: prodView.DetailDescription,
			Groups:            prodView.Groups,
			Skus:              prodView.Skus,
			Nature:            prodView.Nature,
			Status:            false,
		}
	} else {
		if skus, err = s.dao.FindShelfSkusByProdIds(ctx, req.Token.SgId, req.Id, []uint64{req.ProdId}); err != nil {
			return
		}
		resp = &mall.GetCustomerProdResp{
			Id:                req.ProdId,
			Name:              getCustomName(shelfProd),
			PriceRange:        getPriceRangeDict(skus)[req.ProdId],
			Sales:             0,
			HasProperties:     len(prodView.Skus) > 1,
			Unit:              prodView.Unit,
			TitlePics:         prodView.TitlePics,
			DetailPics:        prodView.DetailPics,
			DetailDescription: prodView.DetailDescription,
			Groups:            prodView.Groups,
			Skus:              make([]*prod.SkuView, len(skus)),
			Nature:            prodView.Nature,
			Status:            shelfProd.ShelfStatus,
		}
		for i, sku := range skus {
			resp.Skus[i] = &prod.SkuView{
				Id:     sku.SkuId,
				Name:   strings.Join(sku.SyncItems, "/"),
				Price:  uint32(getCustomPrice(sku)),
				Weight: sku.SyncWeight,
				Items:  sku.SyncItems,
			}
		}
	}
	return
}

// 查看商品分组
func (s *Service) GetCustomerGroups(ctx context.Context, req *mall.CustomerStoreRequest) (
	resp *mall.GetCustomerGroupsResp, err error) {
	var groups []*model.ShelfGroup
	if groups, err = s.dao.FindShelfGroupsBySgId(ctx, req.Token.SgId, req.Id); err != nil {
		return
	}
	resp = &mall.GetCustomerGroupsResp{
		Groups: make([]*mall.GroupSimpleView, len(groups)),
	}
	for i, group := range groups {
		resp.Groups[i] = &mall.GroupSimpleView{
			Id:   group.ID,
			Name: group.Name,
		}
	}
	return
}

// 获取直播房间号
func (s *Service) GetMallWechatRoomID(ctx context.Context, req *mall.CustomerRequest) (
	resp *mall.GetRoomIdReply, err error) {
	resp = &mall.GetRoomIdReply{}
	var sourceType pay.SourceType
	if sourceType, err = getSourceType(req.Token); err != nil {
		return
	}
	switch sourceType {
	case pay.SourceType_mall_mina:
	default:
		err = ecode.BadRequest("只允许微信用户获取")
	}
	if resp.RoomId, err = s.downstream.GetWechatMiniLivingRoom(ctx, req.Token.AppId); err != nil {
		return
	}
	return
}
